<template>
  <a-table 
    v-bind="$attrs" :dataSource="mDataSource" 
    :pagination="simple?false:mPagination"
    :columns="mColumns"
    :rowKey="rowKey"
    :size="sizeRef"
    @change="handleTableChange"
    >
    <template #[key]="data" v-for="(item, key) in $slots">
      <slot :name="key" v-bind="data || {}"></slot>
    </template>
    <template #title>
      <TableToolbar 
      ref="tableToolbarRef"
      :cacheKey="cacheKey"
      :showSettings="showSettings" 
      :regisiter="regisiter" 
      :columns="columns">
        <template #tableToolbarLeft>
          <slot name="tableToolbarLeft"></slot>
        </template>
        <template #tableToolbarCenter>
          <slot name="tableToolbarCenter"></slot>
        </template>
        <template #tableToolbarRight>
          <slot name="tableToolbarRight"></slot>
        </template>
      </TableToolbar>
    </template>
  </a-table>
</template>
<script setup lang="ts">
import { PropType, onMounted, ref, watch, h } from 'vue';
import type { PaginationProps } from 'ant-design-vue';
import request from '/@/utils/request'
import { SorterResult } from 'ant-design-vue/es/table/interface';
import { TreeNode, TreeNodeProps } from '/@/utils/tree';
import TableAction from './TableAction.vue'
import TableToolbar from './TableToolbar.vue';
import { ActionItem, MTableColumnType, TableActionType } from './types';
import ViewMap from '/@/components/view'
// 定义事件
const emits = defineEmits(['change'])
// 定义属性
const props = defineProps({
  api: { // 接口地址或接口函数--->新增属性
    type: [Function, String] as PropType<((param: any)=>Promise<any>) | String>
  },
  pagination: { // 当这里定义了和attrs一样的属性的时候，v-bind="$attrs"就会忽略该属性
    type: Object as PropType<PaginationProps>
  },
  defaultSorter: { // 排序的默认配置--->新增属性
    type: Object as PropType<SorterResult>
  },
  columns: { // 列定义，当这里定义了和attrs一样的属性的时候，v-bind="$attrs"就会忽略该属性
    type: Array as PropType<MTableColumnType[]>,
    default() {
      return []
    }
  },
  simple: { // 简单数据--树，id/parentId/name
    type: Object as PropType<TreeNodeProps>
  },
  rowKey: {
    type: [String],
    default: 'id'
  },
  actions: { // 操作列
    type: Object as PropType<ActionItem[]>
  },
  dropdownActions: { // 下拉操作
    type: Object as PropType<ActionItem[]>
  },
  showSettings: { // 是否显示最右边设置区
    type: Boolean,
    default: true
  },
  size: { // 表格大小
    type: String
  },
  cacheKey: { // 缓存key
    type: String
  },
  // 是否立即执行
  immediate: {
    type: Boolean,
    default: true
  },
  params: { // 静态请求参数
    type: Object as PropType<any>
  },
  beforeFetch: { // 请求参数动态处理
    type: Function as PropType<(p: any)=> any>
  }
})
const sizeRef = ref<String | undefined>(props.size)
const tableToolbarRef = ref()
watch(()=>props.size,()=>{
  sizeRef.value = props.size
})
// 定义排序对象
const mSorter = ref<SorterResult>({
  order: 'ascend',
  ...props.defaultSorter
})
/**
 * 将id/pid/name数据==>children数据
 * @param data 
 */
const toTreeData = (data: Array<any>) => {
  const res = new TreeNode(props.simple || {}).build(data, '0')
  return res
}
/**
 * 处理表格列定义数据
 * @param arr 
 */
const handleColumns = (arr: Array<MTableColumnType>)=>{
  if(!props.defaultSorter) {
    // 如果默认的排序字段未配置，则使用第一个定义有sorter和defaultSortOrder的列
    const defaultSorterColumn: MTableColumnType | undefined = arr?.find(column=>{
      return column.sorter && column.defaultSortOrder
    })
    if(defaultSorterColumn)  {
      mSorter.value = {
        ...mSorter.value,
        field: defaultSorterColumn.key,
        order: defaultSorterColumn.defaultSortOrder
      }
    }
  }
  arr?.forEach(column=>{
    // 处理默认排序
    if(column.key == mSorter.value.field) {
      column.sorter = true
      column.defaultSortOrder = mSorter.value.order || 'ascend'
    } else {
      column.defaultSortOrder = undefined
    }
    if(!column.customRender && column.component) {
      const viewCom = ViewMap[column.component as any] || ViewMap['Default']
      column.customRender = (e: any) => {
        return h(viewCom, {
          data: e,
          column
        })
      }
    }
  })
  if(props.actions && props.actions.length) {
    return [
      ...arr,
      {
      title: '操作',
      dataIndex: '__ACTION__',
      key: '__ACTION__',
      align: 'center',
      customRender(data: any): any{
        return h(TableAction,{
          actions: props.actions,
          dropdownActions: props.dropdownActions,
          data
        })
      }
      } as MTableColumnType
    ]
  } else {
    return arr
  }
}
// 数据源
const mDataSource = ref([])
// 列定义
const mColumns = ref<Array<MTableColumnType>>(handleColumns(props.columns))
// 分页对象定义
const mPagination = ref<PaginationProps>({
  current: 1,
  pageSize: 10,
  total: 0,
  showQuickJumper: true,
  ...props.pagination
})
watch(()=>props.columns,()=>{
    regisiter.updateColumns(props.columns)
},{
  deep: true
})
// 监听分页对象
watch(()=>props.pagination,()=>{
  mPagination.value = {
    ...mPagination.value,
    ...props.pagination
  }
  requestData({})
}, {
  deep: true
})
const requestData = (params: any): Promise<any> => {
  let apiFun: ((param: any)=>Promise<any>) | undefined
  return new Promise((resolve, reject)=>{
    if(props.api && typeof props.api == 'function') {
      apiFun = props.api
    } else if(props.api && typeof props.api == 'string') {
      apiFun = (param: any) => request.post(props.api as any, param)
    }
    if(apiFun) {
      const sorter = mSorter.value
      let reqeustParams = {
        pageNum: mPagination.value.current,
        pageSize: mPagination.value.pageSize,
        orderBy: (sorter.order && sorter.field)?`${sorter.field} ${sorter.order.replace('end','')}`:undefined,
        ...params,
        ...props.params
      }
      if(props.beforeFetch && typeof props.beforeFetch == 'function') {
        reqeustParams = props.beforeFetch(reqeustParams)
      }
      apiFun(reqeustParams).then((res: any)=>{
        if(props.simple) {
          mDataSource.value = toTreeData(res.data.rows || res.data) as any
        } else {
          mPagination.value.total = res.data.recordCount || res.data.length
          mDataSource.value = res.data.rows || res.data
        }
        resolve(res)
      }).catch(reject)
    } else {
      resolve({})
    }
  })
}
/**
 * 表格事件处理
 * @param pagination 
 * @param filters 
 * @param sorter 
 */
const handleTableChange = (pagination: PaginationProps,filters: any,sorter: any) => {
  mPagination.value = {
    ...mPagination.value,
    ...pagination
  }
  mSorter.value = {
    ...mSorter.value,
    ...sorter
  }
  emits('change', mPagination.value, filters, mSorter.value)
  requestData({})
}
const regisiter = {
  reload(opt) {
    return requestData(opt)
  },
  setTableSize(size) {
    sizeRef.value = size
    tableToolbarRef.value?.setMiDuSelectdKeys([size])
  },
  updateColumns(columns) {
      mColumns.value = handleColumns(columns)
  },
} as TableActionType
onMounted(()=>{
  if(props.immediate) {
    requestData({})
  }
})
defineExpose({
  ...regisiter
})
</script>
<style lang="less" scoped>

</style>